package cn.supermaster.management.schedule.quartz;

import cn.supermaster.management.common.constant.Constants;
import cn.supermaster.management.common.constant.ScheduleConstant;
import cn.supermaster.management.common.utils.ExceptionUtil;
import cn.supermaster.management.common.utils.TextUtils;
import cn.supermaster.management.common.utils.bean.BeanUtils;
import cn.supermaster.management.common.utils.spring.SpringUtils;
import cn.supermaster.management.schedule.domain.ScheduleTask;
import cn.supermaster.management.schedule.domain.ScheduleTaskLog;
import cn.supermaster.management.schedule.service.IScheduleTaskLogService;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
 * All rights Reserved, Designed By www.super-bytecode.com
 *
 * @ProjectName: supermaster-management
 * @Package: cn.supermaster.management.task.service.impl
 * @ClassName: ScheduleTaskAbstract
 * @Description: [抽象quartz调用]
 * <p> </p>
 * @Author: [Lance Ting]
 * @Date: 2021/1/13 10:22
 * @Version: V1.0
 * @Copyright: 2021 www.super-bytecode.com Inc. All rights reserved.
 * TODO: 注意,本文件Lance Ting所作,如果转载或使用请标明具体出处!
 **/
public abstract class ScheduleTaskAbstract implements Job {

    private static final Logger logger = LoggerFactory.getLogger(ScheduleTaskAbstract.class);

    /**
     * 线程本地变量
     */
    private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();

    /***
     * @description: [定时任务执行器]
     * <p></P>
     * @title: execute
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: context
     * @return: void
     */
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        ScheduleTask scheduleTask = new ScheduleTask();
        Exception ex = null;// 异常信息
        try {
            // 执行器上下文获取对象
            JobDataMap mergedJobDataMap = context.getMergedJobDataMap();
            Object jobDataMap = mergedJobDataMap.get(ScheduleConstant.TASK_PROPERTIES);
            BeanUtils.copyBeanProp(scheduleTask, jobDataMap);
            before(context, scheduleTask);
            if (scheduleTask != null) {
                // 任务执行
                doExecute(context, scheduleTask);
            }
        } catch (Exception e) {
            ex = e;
            logger.error("任务执行异常  - ：", e.getMessage());
        }
        //
        after(context, scheduleTask, ex);
    }

    /**
     * @description: [任务执行前操作]
     * <p>设置执行开始时间</P>
     * @title: before
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: context 工作执行上下文对象
     * n@Param: sysJob  系统计划任务
     * @return: void
     */
    protected void before(JobExecutionContext context, ScheduleTask scheduleTask) {
        // 设置执行开始时间
        threadLocal.set(new Date());
    }

    /**
     * @description: [执行后]
     * <p></P>
     * @title: after
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: context 工作执行上下文对象
     * @Param: sysJob  系统计划任务
     * @Param: exception 异常对象
     * @return: void
     */
    protected void after(JobExecutionContext context, ScheduleTask scheduleTask, Exception exception) {
        // 本地线程对象获取执行开始时间
        Date startTime = threadLocal.get();
        threadLocal.remove();
        //
        final ScheduleTaskLog scheduleTaskLog = new ScheduleTaskLog();
        scheduleTaskLog.setJobName(scheduleTask.getJobName());
        scheduleTaskLog.setJobGroup(scheduleTask.getJobGroup());
        scheduleTaskLog.setInvokeTarget(scheduleTask.getInvokeTarget());
        scheduleTaskLog.setStartTime(startTime);
        scheduleTaskLog.setEndTime(new Date());
        long runMs = scheduleTaskLog.getEndTime().getTime() - scheduleTaskLog.getStartTime().getTime();
        scheduleTaskLog.setJobMessage(scheduleTaskLog.getJobName() + " 总共耗时：" + runMs + "毫秒");
        if (exception != null) { //执行失败记录
            scheduleTaskLog.setStatus(Constants.FAIL);
            String exceptionMessage = ExceptionUtil.getExceptionMessage(exception);
            String errorMsg = TextUtils.substring(exceptionMessage, 0, 2000);
            scheduleTaskLog.setExceptionInfo(errorMsg);
        } else {
            scheduleTaskLog.setStatus(Constants.SUCCESS);
        }

        // 写入数据库当中
        SpringUtils.getBean(IScheduleTaskLogService.class).addJobLog(scheduleTaskLog);
    }

    /**
     * @description: [执行方法]
     * <p>由子类重载扩展</P>
     * @title: doExecute
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: context 工作执行上下文对象
     * @Param: sysJob 系统计划任务
     * @return: void
     * @throws: Exception 执行过程中的异常
     */
    protected abstract void doExecute(JobExecutionContext context, ScheduleTask scheduleTask) throws Exception;
}
